package com.lxs.legou.order.listener;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.lxs.legou.order.client.SkuClient;
import com.lxs.legou.order.po.Order;
import com.lxs.legou.order.po.OrderItem;
import com.lxs.legou.order.service.OrderItemService;
import com.lxs.legou.order.service.OrderService;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Envelope;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;

/**
 * @Auther: Mcb
 * @Date: 2022/2/3 21:30
 * @Description: 监听死信队列，订单提交固定时间内未支付时，进行订单删除，库存回滚
 * 使用示例： https://www.cnblogs.com/stonechen/p/14252568.html
 */
@Component
@RabbitListener(queues = "${mq.order.queue.dlx}")
public class OrderLazyStatusListener {

    @Autowired
    private OrderService orderService;
    @Autowired
    private SkuClient skuClient;
    @Autowired
    private OrderItemService orderItemService;

    /**
     *
     * @param str 队列字符串信息
     * @param message 信息对象
     * @param channel 队列
     * 注意：不能使用 envelope 消息包的内容，可从中获取消息id，消息routingkey，交换机，消息和重传标志(收到消息失败后是否需要重新发送)
     *      org.springframework.amqp.core.Message 只能接收简单消息，像字符串、数字这种
     *      org.springframework.messaging.Message 可以接收复杂类型，像对象
     */
    @RabbitHandler
    public void handlerData(String str, Message message, Channel channel) throws IOException {

        try {
            if (StringUtils.isNotEmpty(str)){
                Long orderId = Long.valueOf(str);
                Order order = orderService.getById(orderId);
                if (null != order && !order.getPayStatus().equals("1")){
                    //订单删除处理
                    order.setIsDelete("1");
                    order.setPayStatus("0");
                    order.setOrderStatus("3");
                    orderService.updateById(order);
                    //库存回滚
                    List<OrderItem> orderItems = orderItemService.list(Wrappers.<OrderItem>lambdaQuery().eq(OrderItem::getOrderId,order.getId()));
                    for (OrderItem orderItem : orderItems)
                        skuClient.incrCount(orderItem.getNum(),orderItem.getSkuId());
                    /**
                     * 手动确认：
                     * deliveryTag:该消息的index(message.getMessageProperties().getDeliveryTag())
                     * multiple:是否批量处理.true:将一次性ack所有小于deliveryTag的消息 (1,2两条信息 true：当前为2 则1自动确认)
                     *
                     * 告诉服务器收到这条消息 已经被我消费了 可以在队列删掉 这样以后就不会再发了 否则消息服务器以为这条消息没处理掉 后续还会在发
                     */
                    channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            /**
             * multiple: 仅是代表当前下标信息
             * requeue： 是否重新放回队列
             */
            channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
        }
    }

}
